<?php
namespace app\process;

use Workerman\Worker;
use Workerman\Crontab\Crontab;
use support\Log;
use app\model\RefundRecordModel;
use app\model\BizGoodsTicketModel;
use app\model\BizGoodsOrderModel;
use app\model\UserModel;
use app\model\CardUserModel;
use app\model\BizPayRecordModel;

class Refund
{
	public function onWorkerStart(Worker $worker)
	{
		new Crontab('*/5 * * * * *', function () use ($worker) {
			$refund = RefundRecordModel::where('status','=','doing')
                ->orderBy('id','asc')
                ->first();
			if($refund){
				$this->processRefund($refund);
			}
		});
	}

	/**
	 * 处理退款
	 * @param RefundRecordModel $refund
	 */
	private function processRefund(RefundRecordModel $refund)
	{
		switch($refund->type) {
			case 'biz-order':
				$this->processBizOrderRefund($refund);
				break;
			case 'pay':
				$this->processPayRefund($refund);
				break;
			default:
				Log::error("未知的退款类型: {$refund->type}");
		}
	}

	/**
	 * 处理商家订单退款
	 * @param RefundRecordModel $refund
	 */
	private function processBizOrderRefund(RefundRecordModel $refund)
	{
		$ticket = BizGoodsTicketModel::where('id','=',$refund->item_id)->first();
		if (!$ticket) {
			Log::error("找不到票据: {$refund->item_id}");
			return;
		}

		$order = BizGoodsOrderModel::where('id','=',$ticket->order_id)->first();
		if (!$order) {
			Log::error("找不到订单: {$ticket->order_id}");
			return;
		}

		$this->executeRefund($refund, $order, $ticket, 'ticket');
	}

	/**
	 * 处理支付退款
	 * @param RefundRecordModel $refund
	 */
	private function processPayRefund(RefundRecordModel $refund)
	{
		$bizPayRecord = BizPayRecordModel::where('id','=',$refund->item_id)->first();
		if (!$bizPayRecord) {
			Log::error("找不到支付记录: {$refund->item_id}");
			return;
		}

		$this->executeRefund($refund, $bizPayRecord, $bizPayRecord, 'pay');
	}

	/**
	 * 执行退款操作
	 * @param RefundRecordModel $refund
	 * @param object $order 订单或支付记录
	 * @param object $target 目标对象（票据或支付记录）
	 * @param string $type 类型：ticket 或 pay
	 */
	private function executeRefund(RefundRecordModel $refund, $order, $target, $type)
	{
		// 判断是否为纯卡支付
		if ($this->isPureCardPayment($order)) {
			$this->refundToCard($refund, $order, $target, $type);
		} else {
			$this->refundToBalance($refund, $order, $target, $type);
		}
	}

	/**
	 * 判断是否为纯卡支付
	 * @param object $order
	 * @return bool
	 */
	private function isPureCardPayment($order)
	{
		return $order->card_score > 0 && $order->score <= 0 && $order->money <= 0;
	}

	/**
	 * 退款到卡
	 * @param RefundRecordModel $refund
	 * @param object $order
	 * @param object $target
	 * @param string $type
	 */
	private function refundToCard(RefundRecordModel $refund, $order, $target, $type)
	{
		$cards = json_decode($order->card_score_data, true);
		if (empty($cards)) {
			Log::error("卡支付数据为空");
			return;
		}

		if (count($cards) == 1) {
			// 退到单张卡
			$userCard = CardUserModel::where('id','=',$cards[0]['card_id'])->first();
			if ($userCard) {
				$userCard->score += $refund->refund_amount;
				$userCard->save();
				$this->updateRefundStatus($refund, $target, $type);
			}
		} else {
			// 多张卡退到余额
			$this->refundToBalance($refund, $order, $target, $type);
		}
	}

	/**
	 * 退款到余额
	 * @param RefundRecordModel $refund
	 * @param object $order
	 * @param object $target
	 * @param string $type
	 */
	private function refundToBalance(RefundRecordModel $refund, $order, $target, $type)
	{
		$userId = $order->user_id;
		$user = UserModel::where('id','=',$userId)->first();
		
		if ($user) {
			$user->score += $refund->refund_amount;
			$user->save();
			$this->updateRefundStatus($refund, $target, $type);
		}
	}

	/**
	 * 更新退款状态
	 * @param RefundRecordModel $refund
	 * @param object $target
	 * @param string $type
	 */
	private function updateRefundStatus(RefundRecordModel $refund, $target, $type)
	{
		// 更新退款记录
		$refund->status = 'success';
		$refund->refund_at = time();
		$refund->save();

		// 更新目标对象
        if($type == 'biz-order'){
            $target->status = 3;
        }else if($type == 'pay'){
            $target->refund_status = 2;
        }

        $target->refund_at = time();
        $target->refund_record_id = $refund->id;
        $target->save();
	}
}
